package lschgcdev.apis;
import java.lang.reflect.*;
import java.io.*;
import java.util.*;

public class Settings implements UIDentificable, LifeCycle, Comparable<String>
{
	private LinkedHashMap<String, EventResponse<?>> memoryLocator;
	private final static String LOCATOR_KEY = "_locatorMem_";
	
	private static int unitCounter = 0;
	private final static String SETTING_FILE_EXSTENSION = ".stx";
	
	private String UID;
	private boolean useUC = false;
	
	protected boolean enabled = true;
	
	protected Logger log;
	
	public Settings(){
		useUC = true;
		init();
	}
	
	public Settings(String UID){
		this.UID = UID;
		init();
	}

	@Override
	public int compareTo(String t)
	{
		if(UID.equals(t))
			return 1;
		return 0;
	}
	
	@Override
	public void setEnable(boolean enabled){
		this.enabled = enabled;
	}
	
	@Override
	public void init(){
		if(useUC)
			UID = this.getClass().getSimpleName()+(++unitCounter);
		log = new Logger(this);
	}
	
	@Override
	public void alloc(EventResponse<?> sL){
		memoryLocator.put(LOCATOR_KEY+memoryLocator.size(), sL);
	}
	
	@Override
	public void destroy(){
		for(int index = 0; index < memoryLocator.size(); index++){
			memoryLocator.get(LOCATOR_KEY+index).eventReport("");
			memoryLocator.remove(LOCATOR_KEY+index);
		}
	}
	
	@Override
	public String getUID(){
		return UID;
	}
	
	public void update(Settings target) throws IllegalAccessException, IllegalArgumentException{
		update(target, null);
	}

	public void update(Settings target, SettingMask mask) throws IllegalAccessException, IllegalArgumentException {
		Field[] fT = target.getClass().getFields();
		Field[] fS = this.getClass().getFields();
		if(mask == null)
			mask = new SettingMask(true);

		for(Field flS : fS){
			for(Field flT : fT){
				if(flT.getName().equals(flS.getName()))
					if(mask.verify(flT.getName()))
						flT.set(target, flS.get(this));
			}
		}
	}

	public void load(Settings target) throws IllegalArgumentException, IllegalAccessException{
		Field[] fT = target.getClass().getFields();
		Field[] fS = this.getClass().getFields();

		
		
		for(Field flS : fS){
			System.out.println(flS.getName());
			for(Field flT : fT){
				if(flT.getName().equals(flS.getName()))
					flS.set(this, flT.get(target));
			}
		}
	}
	
	public void load(String path) throws FileNotFoundException, IOException, ClassNotFoundException, IllegalAccessException, IllegalArgumentException{
		FileInputStream fiS = new FileInputStream(path+UID+SETTING_FILE_EXSTENSION);
		ObjectInputStream oiS = new ObjectInputStream(fiS);
		
		Settings bS = (Settings)oiS.readObject();
		this.load(bS);
		
		oiS.close();
		fiS.close();
	}

	public void save(String path) throws FileNotFoundException, IOException {
		FileOutputStream foS = new FileOutputStream(path+UID+SETTING_FILE_EXSTENSION);
		ObjectOutputStream ooS = new ObjectOutputStream(foS);
		
		ooS.writeObject(this);
		
		ooS.close();
		foS.close();
	}
}
